﻿namespace WingBeats.Mvc

open System
open System.Reflection

type WingBeatsControllerFactory() =
    
    static let config = WingBeatsConfigurationSettings.GetSection()
    static let controllerAssembly = Assembly.Load(AssemblyName(config.ControllerAssembly)) 
    static let controllers = 
        let stripSuffix (name:string) =
            if name.EndsWith("Controller") then 
                name.[0 .. name.Length - 11]
            else name
        let baseController = typeof<System.Web.Mvc.Controller>

        controllerAssembly.GetTypes()
        |> Seq.filter (fun t -> baseController.IsAssignableFrom(t))
        |> Seq.map (fun t -> (stripSuffix t.Name, t))
        |> Map.ofSeq

    let throwIfNull x name =
        if x = null then raise <| ArgumentNullException(name)
        ()

    interface System.Web.Mvc.IControllerFactory with
        member this.CreateController(context, controllerName) =
            throwIfNull context "context"
            throwIfNull controllerName "controllerName"
            
            match Map.tryFind controllerName controllers with
            | Some(t) -> Activator.CreateInstance(t) :?> System.Web.Mvc.IController
            | None    -> raise <| System.Web.HttpException(404, 
                                      sprintf "Controller '%s' was not found. Path: %s" 
                                              controllerName
                                              context.HttpContext.Request.Path)

        member this.ReleaseController(controller) =
            match controller with
            | :? IDisposable as d -> d.Dispose()
            | _ -> ()

